import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTCreator;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.exceptions.SignatureVerificationException;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.auth0.jwt.interfaces.JWTVerifier;
import org.apache.commons.lang3.time.DateUtils;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

public class JwtUtils {

    /**
     * 秘钥密码
     */
    private static final String SECRET = "$$$!!!@@@@";

    /**
     * 发布者
     */
    private static final String ISSUER = "sky";

    /**
     * 生成token
     *
     * @param claims 加密对象
     * @return token
     */
    public static String createToken(Map<String, String> claims) throws Exception {
        // org.apache.commons.lang3.time.DateUtils
        Date date = DateUtils.addSeconds(new Date(), 1);
        // DateUtils.addHours(new Date(), 2)
        try {
            Algorithm algorithm = Algorithm.HMAC256(SECRET);
            JWTCreator.Builder builder = JWT.create()
                    .withIssuer(ISSUER)
                    //设置过期时间为2小时
                    .withExpiresAt(date);
            claims.forEach(builder::withClaim);
            return builder.sign(algorithm);
        } catch (IllegalArgumentException e) {
            throw new Exception("生成token失败");
        }
    }

    /**
     * 验证jwt，并返回数据
     */
    public static Map<String, String> verifyToken(String token) throws Exception{
        Algorithm algorithm;
        Map<String, Claim> map;
        algorithm = Algorithm.HMAC256(SECRET);
        try {
            JWTVerifier verifier = JWT.require(algorithm).withIssuer(ISSUER).build();
            DecodedJWT jwt = verifier.verify(token);
            map = jwt.getClaims();
        } catch (TokenExpiredException e) {
            throw new TokenExpiredException("秘钥过期了");
        } catch (SignatureVerificationException e) {
            throw new SignatureVerificationException(algorithm, e);
        } catch (JWTDecodeException e) {
            throw new JWTDecodeException("token不合法");
        }

        Map<String, String> resultMap = new HashMap<>(map.size());
        map.forEach((k, v) -> resultMap.put(k, v.asString()));
        return resultMap;
    }
}